package com.workflow.engine.eb.service;

import com.alibaba.fastjson.JSON;
import com.workflow.engine.core.flow.Constants;
import com.workflow.engine.core.flow.IFlow;
import com.workflow.engine.core.flow.StepState;
import com.workflow.engine.eb.config.FlowConfig;
import com.workflow.engine.parser.misc.ILogger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

import static com.workflow.engine.parser.strategy.StrategyRegister._PARAMS_GENERATOR_STRATEGY;


/**
 * 模板方法实现
 * Created by houjinxin on 16/3/13.
 */
public class EBService implements ILogger {

    private static final Logger logger = LoggerFactory.getLogger(EBService.class);

    private Map<String, Object> getBaseContext(){
        return new HashMap<String, Object>(){{
            //流程配置注册
            put("flow", FlowConfig._FLOW);
            //参数生成策略注册
            put("paramsGeneratorStrategy", _PARAMS_GENERATOR_STRATEGY);
//            put("luaProcess", new LuaProcess("C:\\Users\\Administrator\\Desktop\\Release"));
        }};
    }

    /**
     * 根据业务需要来创建不同的上下文
     *
     * @param bizObject 业务对象放到上下文中被整个流程共享
     * @return
     */
    private Map<String, Object> createContext(Object bizObject) {
        Map<String, Object> baseContext = getBaseContext();
        Map<String, Object> bizContext = createBizContext(bizObject);
        Map<String, Object> context = new HashMap<String, Object>();
        context.putAll(baseContext); //基础上下文
        context.putAll(bizContext); //业务上下文
        return context;
    }

    /**
     * 业务相关上下文,拆解业务对象内容,各家保险公司所需要的信息基本一致
     *
     * @param bizObject
     * @return
     */
    protected Map<String, Object> createBizContext(Object bizObject) {
        final Map<String, String> biz = (Map<String, String>) bizObject;
        return new HashMap<String, Object>(){{
            put("username", biz.get("username"));
            put("password", biz.get("password"));
        }};
    }

    public Object execute(Object bizObject){
        Map<String, Object> context = createContext(bizObject);
        return service(context, (IFlow) context.get("flow"));
    }

    /**
     * 各类流程启动,将最终的处理结果赋值给业务对象
     *
     * @param context 上下文
     * @param flow    流程
     * @return 期望类型的目标对象
     */
    public Object service(Map<String, Object> context, IFlow flow) {
        Object obj = null;
        try {
            long beginTime = System.currentTimeMillis();
            StepState flowState = flow.run(context);
            long endTime = System.currentTimeMillis();
            getLogger().info("调用接口所需时间：{}s", ((endTime - beginTime) / 1000));
            if (flowState.getStatusFlag() == Constants._STEP_SUCCESS_FLAG) {
                obj = getTargetBizObject(context);
            }
        } catch (Exception e) { //针对不同场景定义一些业务异常,在适当时候抛出业务异常
            e.printStackTrace();
            getLogger().error("异常描述如下:\n{}", e);
            return obj;
            //if(e instanceOf BusinessException)
            //非特定业务异常的其他情况转为业务异常抛出
            //throw new BusinessException("")

        }
        return obj;
    }

    /**
     * 流程正确运行返回的结果
     *
     * @param context
     * @return
     */
    private Object getTargetBizObject(Map<String, Object> context) {
        String flowType = (String) context.get("flowType");
        Object targetBizObject = context.get("result");
        getLogger().info("{}[ {} ]流程执行成功,目标业务对象为:\n{}", this.getClass().getSimpleName(), flowType, JSON.toJSON(targetBizObject));
        return targetBizObject;
    }

    @Override
    public Logger getLogger() {
        return logger;
    }
}
